<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" data-ng-app="Alarm" data-ng-controller="TimerController">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale
=1.0, user-scalable=no" />
    <title ng-bind="(past.length > 0 ? '*  ' : '') + current.hours + ':' + '0'.concat(current.minutes).substr(-2,2) + ':' + '0'.concat(current.seconds).substr(-2,2) + '   ' + current.name">Alarms</title>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
    <script src="SevenSegmentDigit.js"></script>
    <script src="SevenSegmentDirectives.js"></script>



    <script>
"use strict";



angular
.module('Alarm', ['SevenSegmentDirectives'])
.controller('TimerController', ['$scope', '$timeout', function($scope, $timeout) {

  $scope.saveAlarms = function() {
    console.log('Saving ' + $scope.alarms.length + ' alarms to database.');
    console.log(JSON.stringify($scope.alarms));
    localStorage.setItem('Alarms', JSON.stringify($scope.alarms));
    console.log($scope.alarms.length + ' alarms saved to database.');
    $scope.current = $scope.alarms[0];
  }

  var updateNext = function(alarm) {
    console.log('Updating the next value for: ', alarm);

    if (alarm.hasOwnProperty('date')) {  //one time alarm
      alarm.date = new Date(alarm.date);
      alarm.next = alarm.date;
      alarm.next.setHours(alarm.time.getHours());
      alarm.next.setMinutes(alarm.time.getMinutes());
      alarm.next.setSeconds(alarm.time.getSeconds());
      alarm.next.setMilliseconds(alarm.time.getMilliseconds());
    } else {  //recurring alarm
      alarm.next = new Date();
      alarm.next.setHours(alarm.time.getHours());
      alarm.next.setMinutes(alarm.time.getMinutes());
      alarm.next.setSeconds(alarm.time.getSeconds());
      alarm.next.setMilliseconds(alarm.time.getMilliseconds());
      while (alarm.next.getTime() < Date.now() || !alarm.weekdays.some(function(ele) { return ele.day == alarm.next.getDay(); })) {
        alarm.next.setDate(alarm.next.getDate() + 1);
      }
    }
  }

  $scope.getAlarms = function() {
    console.log('Retrieving alarms from database.');

    var alarms = JSON.parse(localStorage.getItem('Alarms'));

    if (alarms !== null && alarms.length > 0) {
      for (var i = 0, alarm = alarms[i]; i < alarms.length; alarm = alarms[++i]) {
        console.log('Deserializing alarm.', alarm);
        delete alarm.$$hashKey;
        alarm.time = new Date(alarm.time);
        updateNext(alarm);
      }
    }

    alarms = alarms === null ? [] : alarms;
    alarms.sort(function(a,b){return a.next.getTime() - b.next.getTime();});
    $scope.alarms = alarms;
    $scope.current = $scope.alarms[0];
  }

  //menu variables
  $scope.name = '';
  $scope.time = null;
  $scope.sound = false;
  $scope.date = null;
  $scope.frequency = 'onetime';
  $scope.weekdays = [
    {name: "Sunday",    checked: false, day: 0},
    {name: "Monday",    checked: false, day: 1},
    {name: "Tuesday",   checked: false, day: 2},
    {name: "Wednesday", checked: false, day: 3},
    {name: "Thursday",  checked: false, day: 4},
    {name: "Friday",    checked: false, day: 5},
    {name: "Saturday",  checked: false, day: 6}
  ];

  $scope.past = [];
  $scope.getAlarms();



  $scope.dismiss = function(idx) {
    console.log('Dismissing alarm:', $scope.past[idx]);
    $scope.past.splice(idx, 1);
  }



  $scope.delete = function(alarm) {
    console.log("Deleting alarm.", alarm);
    $scope.alarms.splice($scope.alarms.indexOf(alarm), 1);
    $scope.saveAlarms();
  }



  $scope.resetMenu = function() {
    console.log('Resetting menu.');
    $scope.showMenu = false;
    $scope.date = null;
    $scope.name = '';
    $scope.sound = false;
    $scope.time=null;
    $scope.changeDate();
    $scope.frequency = 'onetime';
  }



  $scope.addAlarm = function() {
    console.log('Attempting to add a new alarm.');
    if (!$scope.formNewAlarm.$valid) {
      console.log('Invalid input.  Attempt failed.');
    } else {
      console.log('Input is valid.  Proceeding with adding new alarm.');
      var alarm = {
        name: $scope.name,
        time: $scope.time,
        sound: $scope.sound
      };
      if ($scope.isSomeWeekdayChecked()) {
        alarm.weekdays = [];
        $scope.weekdays.forEach(function(ele) { if (ele.checked) { alarm.weekdays.push({name: ele.name, day: ele.day}); } });
      } else {
        alarm.date = $scope.date;
      }

      updateNext(alarm);

      console.log('Adding alarm:', alarm);
      $scope.alarms.push(alarm);
      $scope.alarms.sort(function(a,b){return a.next.getTime() - b.next.getTime();});
      $scope.saveAlarms();
      $scope.resetMenu();
    }
  }



  $scope.changeDate = function() {
    $scope.weekdays.forEach(function(ele) { ele.checked = false; });
  }



  $scope.changeWeekday = function() {
    $scope.date = null;
  }



  $scope.isSomeWeekdayChecked = function() {
    return $scope.weekdays.some(function(ele) {return ele.checked ;});
  }



  $scope.isTomorrow = function(alarm) {
    var temp = new Date(alarm.next.getTime());
    temp.setHours(0);
    temp.setMinutes(0);
    temp.setSeconds(0);
    temp.setMilliseconds(0);
    var span = temp.getTime() - Date.now();
    return span < 86400000 && span > 0;
  }



  $scope.setToday = function() {
    console.log('Set date to today.');
    var today = new Date();
    $scope.date = new Date(today.getFullYear(), today.getMonth(), today.getDate());
    $scope.changeDate();
  }



  $scope.beep = function() {
    var c = new AudioContext();  //TOOD handle lame chrome
    var o = c.createOscillator();
    o.frequency.value = 3100;
    o.type = 'sawtooth';
    o.connect(c.destination);
    o.start(0);
    o.stop(.5);

    $timeout(function() { o.disconnect(c.destination);}, 100);
    $timeout(function() { o.connect(c.destination);}, 300);
  }



  $scope.getOpacity = function(alarm) {
    var _12H = 43200000;  //catches today's events
    var _36H = 129600000;  //catches tomorrow's events
    var _1W = 950400000;  //catches events the remainder of this week and next week

    if (alarm.remainingMS < _12H) {  //.8 - .4
      return .8 - alarm.remainingMS / _12H * .4;
    } else if (alarm.remainingMS < _36H) {  //.4 - .3
      return .4 - alarm.remainingMS / _36H * .1;
    } else if (alarm.remainingMS < _1W) {  //.3 - .05
      return .3 - alarm.remainingMS / _1W * .25;
    } else {
      return .05;
    }
  }



  var tick = function() {
    $scope.now = new Date();

    for (var i = 0, alarm = $scope.alarms[i]; i < $scope.alarms.length; alarm = $scope.alarms[++i]) {
      var remainingMS = alarm.remainingMS = alarm.next.getTime() - $scope.now.getTime();

      if (alarm.remainingMS < 0 && $scope.past.indexOf(alarm) === -1) {
        if (alarm.sound) {
          $scope.beep();
        }
        $scope.past.push({name:alarm.name, next: new Date(alarm.next.getTime())});
        if (alarm.hasOwnProperty('date')) {  //one time alarm
          $scope.alarms.splice($scope.alarms.indexOf(alarm), 1);
          $scope.saveAlarms();
        } else {  //recurring
          updateNext(alarm);
          $scope.alarms.sort(function(a,b){return a.next.getTime() - b.next.getTime();});
        }
        $scope.current = $scope.alarms[0];
      }

      alarm.days = remainingMS / (1000 * 60 * 60 * 24) | 0;
      remainingMS -= (alarm.days * (1000 * 60 * 60 * 24));
      alarm.hours = remainingMS / (1000 * 60 * 60) | 0;
      remainingMS -= (alarm.hours * 1000 * 60 * 60);
      alarm.minutes = remainingMS / (1000 * 60) | 0;
      remainingMS -= (alarm.minutes * 1000 * 60);
      alarm.seconds = remainingMS / (1000) | 0;
      
      alarm.secondOne = alarm.seconds % 10;
      alarm.secondTen = alarm.seconds / 10 | 0;
      alarm.minuteOne = alarm.minutes % 10;
      alarm.minuteTen = alarm.minutes / 10 | 0;
      alarm.hourOne = alarm.hours % 10;
      alarm.hourTen = alarm.hours / 10 | 0;
    }

    $timeout(tick, 1002 - new Date().getMilliseconds());
  }



  $timeout(tick, 0);

}]);



    </script>



    <style>
      body{margin:0;background:#263238;font-family:'Roboto',sans-serif;}
      digit,clock{display:inline-block;}
      input{font-size:16px;padding:3px;border-size:1px;}

      input[type="button"]{border-radius:5px;border:none;cursor:pointer;font-weight: bold;transition:all ease .5s;}

      #btnShowMenu{z-index:2;background:#ff6e40;box-shadow:0px 0px 5px rgba(0, 0, 0, 0.87);color:rgba(255, 255, 255, 0.87);font-size:2em;position:fixed;right:10px;bottom:10px;}

      #formNewAlarm{
       color: rgba(0, 0, 0, 0.87);
       font-size: 1.2em;
       padding:0 16px;
       position:fixed;
       background:#eceff1;
       right:0;
       left:0;
       bottom:0;
       transform: translateY(425px);
       transition:all ease 0.5s;
       z-index:3;
     }


     #formNewAlarm.show{transform: translateY(0px);}
      .inputLabel{font-size:12px;color:rgba(0,0,0,.54);margin-top:16px;}
      input[type="text"],input[type="time"],input[type="date"]{border:none;border-bottom:solid 1px rgba(0,0,0,.26);background:none;margin-bottom:8px;padding:8px 0;}
      input[type="text"]:focus,input[type="time"]:focus,input[type="date"]:focus{border-bottom-color:#ff6e40;}
      input[type="text"],input[type="time"],input[type="date"],label{font-size:16px;color:rgba(0,0,0,.87);}

      input[type="submit"],input[type="reset"]{margin:16px;}

      .bell{cursor:pointer;}

      .current{transition:all ease .5s;}
      .current{text-align:center;padding:50px 25px;}
      .current:hover{background:rgba(255,255,255,.05);}
      .current header{text-align:left;color:hsla(14, 100%, 63%, .87);font-size:24px;font-weigh:bold;}
      .current footer{text-align:right;color:rgba(255,255,255,.26);opacity:0;font-size:12px;}
      .current:hover footer{opacity:1;}
      .current:hover input[type="button"]{opacity:1;}
      .current .bell{position:absolute;top:50px;right:25px;color:rgba(255, 255, 255, 0.26);}
      .current .bell.active{color:hsla(14, 100%, 63%, .87);}


      /*.today{transition:all ease .5s;}*/
      .today{padding:5px 50px;}
      .today:hover{background:rgba(255,255,255,.05);}
      .today clock{margin-left:25px;}
      .today header{text-align:left;color:hsla(14, 100%, 63%, .87);font-size:16px;}
      .today footer{float:right;text-align:right;color:rgba(255,255,255,.26);opacity:0;font-size:12px;}
      .today:hover footer{opacity:1;}
      .today:hover input[type="button"]{opacity:1;}
      .today .bell{float:left;color:rgba(255, 255, 255, 0.26);margin-right:5px;}
      .today .bell.active{color:hsla(14, 100%, 63%, .87);}

      .today{opacity:.8;}
      .tomorrow{opacity:.4;}
      .future{opacity:.1;}

      .today:hover,.tomorrow:hover,.future:hover{opacity:1 !important;}

/*
      .today{transition:all ease .5s;}
      .today{padding:5px 50px;}
      .today:hover{background:rgba(255,255,255,.05);}
      .today clock{margin-left:25px;}
      .today header{text-align:left;color:hsla(14, 100%, 63%, .54);font-size:16px;}
      .today footer{float:right;color:rgba(255,255,255,.26);opacity:0;font-size:12px;}
      .today:hover footer{opacity:1;}
      .today:hover input[type="button"]{opacity:1;}
      .today .bell{float:left;color:rgba(255, 255, 255, 0.26);margin-right:5px;}
      .today .bell.active{color:hsla(14, 100%, 63%, .87);}

      .tomorrow header{color:hsla(14, 100%, 63%, .26);}
      .tomorrow .bell{color:rgba(255, 255, 255, .05);}
      .tomorrow .bell.active{color:hsla(14, 100%, 63%, .26);}

      .future header{color:hsla(14, 100%, 63%, .1);}
      .future .bell{color:rgba(255, 255, 255, .01);}
      .future .bell.active{color:hsla(14, 100%, 63%, .1);}

      .future:hover header{color:hsla(14, 100%, 63%, .87);}
*/
      .past{background:#5af158;margin-bottom: 1em;position:relative;}
      .past .name{color:rgba(0,0,0,.8);font-size:1.2em;font-weight:bold;}
      .past .next{color:rgba(0,0,0,.54);}
      .past input[type="button"]{opacity:0;position:absolute;top:3px;right:3px;}
      .past:hover input[type="button"]{opacity:1;}

      /*.tomorrow,.future{color:rgba(255, 255, 255, 0.54);padding:10px 50px;}*/

      .triangle{transition:all ease .5s;position:absolute;left:25px;cursor:pointer;}
      .triangle.rotate{transform:rotate(90deg);}

    </style>



  </head>
  <body>

    <input type="button" id="btnShowMenu" value="+" ng-click="showMenu = true;" ng-init="showMenu = false" />

    <form id="formNewAlarm" name="formNewAlarm" ng-class="{'show': showMenu}" novalidate ng-submit="addAlarm()">
      <!-- Name -->
      <div class='inputLabel'>Alarm Name</div>
      <input type="text" id="txtName" name="txtName" ng-model="name" placeholder="e.g., lunch, retirement" size="50" required />
      <!-- Time -->
      <div class='inputLabel'>Time</div>
      <input type="time" id="txtTime" name="txtTime" ng-model="time" placeholder="HH:MM" size="5" required />
      <!-- Sound -->
      <div class='inputLabel'>Sound</div>
      <input type="checkbox" ng-model="sound" />

      <div class="inputLabel">Alarm Frequency</div>
      <label><input type="radio" name="rblFrequency" ng-model="frequency" value="onetime" /> One Time</label>
      <label><input type="radio" name="rblFrequency" ng-model="frequency" value="recurring" /> Recurring</label>

      <div ng-show="frequency == 'onetime'" class='inputLabel'>
        <!-- Date -->
        <div>Date</div>
        <input type="date" id="txtDate" name="txtDate" ng-model="date" ng-change="changeDate()" placeholder="yyyy-MM-dd" size="10" ng-required="!isSomeWeekdayChecked()" />
        <input type="button" value="&#128197;" ng-click="setToday()" />
      </div>

      <div ng-show="frequency == 'recurring'" class='inputLabel'><!-- Days of Week -->
        <div ng-repeat="w in weekdays">
          <label>
            <input type="checkbox" ng-model="weekdays[$index].checked" ng-change="changeWeekday()">
            {{w.name}}
          </label>
        </div>
      </div>

      <div><!-- Submit & Reset/Cancel Button -->
        <input type="submit" value="add" />
        <input type="button" value="Cancel" ng-click="resetMenu();" />
      </div>
    </form>



    <div data-ng-repeat="a in past" class="past">
      <span class="name">{{a.name}}</span>
      <span class="next">{{a.next | date: "MMM d, y 'at' h:mm a"}}</span>
      <input type="button" value="&#x2716;" ng-click="dismiss($index)" />
    </div>



    <div class="current">
      <header>
        <span>{{current.name}}</span>
        <div class="bell" ng-class="{'active': current.sound}" ng-click
="current.sound = !current.sound;saveAlarms();">&#x1f514;</div>
      </header>
      <clock alarm="current" size="75"></clock>
      <footer>
        <span ng-hide="current.date">
          repeats every 
          <span ng-repeat="w in current.weekdays">
            <span ng-if="$last && !$first"> and </span>
            {{w.name}}
            <span ng-if="!$last && current.weekdays.length > 2">, </span>
          </span>
          at {{current.time | date: 'h:mm a'}}
          <span class="next">next: {{current.next | date: "MMM d, y 'at' h:mm a"}}</span>
        </span>
        <span ng-show="current.date">on {{current.next | date: "MMM d, y 'at' h:mm a"}}</span>
        <input type="button" value="&#x2716;" ng-click="delete(current)" />
      </footer>
    </div>



    <div data-ng-repeat="a in alarms" class="today" ng-if="!$first" ng-style="{'opacity': getOpacity(a)}">
      <header>
        <span>{{a.name}}</span>
        <div class="bell" ng-class="{'active': a.sound}" ng-click="a.sound = !a.sound;saveAlarms();">&#x1f514;</div>
      </header>
      <clock alarm="a" size="10"></clock>
      <footer>
        <span ng-hide="a.date">
          repeats every 
          <span ng-repeat="w in a.weekdays">
            <span ng-if="$last && !$first"> and </span>
            {{w.name}}
            <span ng-if="!$last && a.weekdays.length > 2">, </span>
          </span>
          at {{a.time | date: 'h:mm a'}}
          <span class="next">next: {{a.next | date: "MMM d, y 'at' h:mm a"}}</span>
        </span>
        <span ng-show="a.date">on {{a.next | date: "MMM d, y 'at' h:mm a"}}</span>
        <input type="button" value="&#x2716;" ng-click="delete(a)" />
      </footer>
    </div>



  </body>
</html>